home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / database / postgres / mpsql-1.001 / mpsql-1~ / mpsql-1.0 / db.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-29  |  25.2 KB  |  771 lines

  1. /************************************************************************/
  2. /* Module : db.c                                */
  3. /* Purpose: database module                                */
  4. /* By     : Keith R. Davis                            */
  5. /* Date   : 12/11/95                                    */
  6. /* Notes  : Copyright(c) 1996 Whit River Software            */
  7. /*          Copyright(c) 1994, Regents of the University of California  */
  8. /************************************************************************/
  9.  
  10. #include <Xm/Xm.h>            /* motif lib header        */
  11. #include <Xm/CutPaste.h>                /* motif clipboard header       */
  12. #include <Xm/Text.h>                  /* text widget header        */
  13. #include <X11/cursorfont.h>             /* X cursors                    */ 
  14. #include <string.h>            /* string header        */
  15. #include <stdio.h>                      /* stdio header                 */
  16. #include <pwd.h>                        /* passwd header                */
  17.  
  18. #include "mquel.h"                      /* mquel module header          */
  19. #include "llist.h"                      /* linked list header           */
  20. #include "db.h"                /* db data header        */
  21. #include "util.h"                       /* utility function header      */
  22.  
  23. /* databse globals , this needs to be eliminated !! */    
  24.     
  25. PGconn *db = NULL;                /* db ptr                */
  26. char dbname[DB_NAME_SZ];        /* db name                  */
  27. char host[HOST_NAME_SZ];                  /* host name                     */
  28. char port[PORT_NAME_SZ];        /* port                 */
  29. char spool_file[MAX_PATH_LEN];          /* spool file                   */         
  30. char printer[PRINT_NAME_SZ];            /* printer                      */
  31. int col_width;                          /* default column width         */ 
  32. int connected = 0;                      /* connect flag                 */
  33.  
  34.  
  35. /************************************************************************/
  36. /* Function: DB_Connect                                                 */
  37. /* Purpose : establishes connection to postgres database                */
  38. /* Params  :                                                            */
  39. /* Returns : 1 on SUCCESS / 0 on FAILURE                                */
  40. /* Notes   :                                                            */
  41. /************************************************************************/
  42.  
  43. int DB_Connect(void)
  44. {
  45.   char db_msg[ERR_MSG_SIZE];
  46.  
  47.   DB_Grab();
  48.  
  49.   if(connected)
  50.     PQfinish(db);
  51.  
  52.   db = PQsetdb(host, port, NULL, NULL, dbname);
  53.  
  54.   if (PQstatus(db) == CONNECTION_BAD) {
  55.  
  56.     sprintf(db_msg,"Connection to database '%s' failed.\nERROR: %s", 
  57.         dbname, PQerrorMessage(db));
  58.     ErrorMsg("Connect", db_msg);
  59.     sprintf(db_msg,"Not connected.");
  60.     XtVaSetValues(AppWidgetsPtr->message,
  61.           XtVaTypedArg, XmNlabelString, XmRString,
  62.           db_msg, strlen(db_msg)+1, NULL);
  63.     connected = 0;
  64.     DB_UnGrab();
  65.     return 0;
  66.   }    
  67.   sprintf(db_msg,"Connected to database '%s'.", dbname); 
  68.   connected = 1;
  69.   XtVaSetValues(AppWidgetsPtr->message,
  70.           XtVaTypedArg, XmNlabelString, XmRString,
  71.           db_msg, strlen(db_msg)+1, NULL);
  72.  
  73.   DB_UnGrab();
  74.  
  75.   return 1;
  76. }
  77.  
  78. /************************************************************************/
  79. /* Function: DB_Close                                                   */
  80. /* Purpose : kills connection to postgres database                      */
  81. /* Params  :                                                            */
  82. /* Returns :                                                            */
  83. /* Notes   :                                                            */
  84. /************************************************************************/
  85.  
  86. void DB_Close(void)
  87. {
  88.   /* disconnect from database */
  89.   if(connected)
  90.     PQfinish(db);
  91. }
  92.  
  93. /************************************************************************/
  94. /* Function: DB_SubmitQy                                                */
  95. /* Purpose : submits SQL window contents to postgres database           */
  96. /* Params  :                                                            */
  97. /* Returns : 1 on SUCCESS / 0 on FAILURE                                */
  98. /* Notes   :                                                            */
  99. /************************************************************************/
  100.  
  101. int DB_SubmitQy(void)
  102. {
  103.   char *qy_ptr;
  104.   int buf_pos;
  105.   int qy_pos;
  106.   int qy_len;
  107.   int selected = 0;
  108.   char db_msg[ERR_MSG_SIZE];
  109.   char qy_buffer[QY_BUFFER_SIZE];
  110.   PGresult* results;
  111.   PGnotify* notify;
  112.  
  113.   if (!connected) {
  114.     sprintf(db_msg,"No Connection to database.");
  115.     ErrorMsg("Query", db_msg);
  116.     return 0;
  117.   }
  118.  
  119.   if((char*)XmTextGetSelection(AppWidgetsPtr->sqlwindow)!= NULL){
  120.     qy_ptr = (char*)doubleTrim((char*)XmTextGetSelection(AppWidgetsPtr->sqlwindow));
  121.     selected = 1;
  122.   }
  123.   else
  124.     qy_ptr = (char*)doubleTrim((char*)XmTextGetString(AppWidgetsPtr->sqlwindow));
  125.   
  126.   if((qy_len = strlen(qy_ptr)) == 0){
  127.     if(selected)
  128.       XtFree(qy_ptr);
  129.     return 0;
  130.   }
  131.  
  132.   qy_pos = 0;
  133.  
  134.   DB_Grab();
  135.  
  136.   while(qy_pos < qy_len){
  137.     buf_pos = 0;
  138.  
  139.     while((qy_ptr[qy_pos] != ';') && (qy_pos < qy_len)){
  140.       qy_buffer[buf_pos++] = qy_ptr[qy_pos++];
  141.       if(strlen(qy_buffer) > (QY_BUFFER_SIZE - 2)){
  142.     sprintf(db_msg,"Query length exceeds max. query size, truncated at %d\n", 
  143.         QY_BUFFER_SIZE);
  144.     DB_WriteToResult(db_msg, 0, NULL);
  145.     break;
  146.       }
  147.     }
  148.  
  149.     qy_pos++;
  150.     qy_buffer[buf_pos++] = ';';
  151.     qy_buffer[buf_pos] = '\0';
  152.  
  153.     results = PQexec(db, (char*)doubleTrim(qy_buffer));
  154.     if (results == NULL) {
  155.       DB_UnGrab();
  156.       DB_WriteToResult(PQerrorMessage(db), 0, NULL);
  157.       return 0;
  158.     }
  159.     
  160.     switch (PQresultStatus(results)) {
  161.     case PGRES_TUPLES_OK:
  162.       DB_PrintTuples(qy_buffer,
  163.              results,
  164.              spool_file,
  165.              XmToggleButtonGetState(AppWidgetsPtr->tglspool),  
  166.              XmToggleButtonGetState(AppWidgetsPtr->tglcol),
  167.              XmToggleButtonGetState(AppWidgetsPtr->tglecho),
  168.              col_width,
  169.              GetColSeparator()
  170.              );
  171.       PQclear(results);
  172.       break;
  173.     case PGRES_EMPTY_QUERY:
  174.       /* do nothing */
  175.       break;
  176.     case PGRES_COMMAND_OK:
  177.       sprintf(db_msg,"%s\n\n",PQcmdStatus(results));
  178.       DB_WriteToResult(db_msg, 0, NULL);
  179.       break;
  180.     case PGRES_COPY_OUT:
  181.       DB_HandleCopyOut(results);
  182.       PQclear(results);
  183.       break;
  184.     case PGRES_COPY_IN:
  185.       DB_HandleCopyIn(results);
  186.       PQclear(results);
  187.       break;
  188.     case PGRES_NONFATAL_ERROR:
  189.     case PGRES_FATAL_ERROR:
  190.     case PGRES_BAD_RESPONSE:
  191.       DB_WriteToResult(PQerrorMessage(db), 0, NULL);
  192.       break;
  193.     } 
  194.     
  195.     /* check for asynchronous returns */
  196.     notify = PQnotifies(db);
  197.     if (notify) {
  198.       sprintf(db_msg,"ASYNC NOTIFY of '%s' from backend pid '%d' received", 
  199.           notify->relname, notify->be_pid);
  200.       DB_WriteToResult(db_msg, 0, NULL);
  201.       free(notify);
  202.     }
  203.   }
  204.   if(selected)
  205.       XtFree(qy_ptr);
  206.   DB_UnGrab();
  207.   return 1;
  208. }
  209.  
  210. /************************************************************************/
  211. /* Function: DB_OpenFile                                                */
  212. /* Purpose : opens a file into the SQL window                           */
  213. /* Params  : file : string w/ filename                                  */
  214. /* Returns : 1 on SUCCESS / 0 on FAILURE                                */
  215. /* Notes   :                                                            */
  216. /************************************************************************/
  217.  
  218. int DB_OpenFile(char *file)
  219. {
  220.   FILE *sqlf;
  221.   char db_msg[ERR_MSG_SIZE];
  222.   char dataString[DATA_SIZE];
  223.   XmTextSource txt_src;
  224.   LLISTbuffer *tmp_buffer;
  225.  
  226.   if((sqlf = fopen(file, "rw")) == NULL){
  227.     sprintf(db_msg, "Error opening: %s", file);
  228.     ErrorMsg("Open File", db_msg);
  229.     return 0;
  230.   }
  231.  
  232.   if((tmp_buffer = LLIST_Insert(0, file, buffer_tail)) == NULL){
  233.     sprintf(db_msg, "Not enough memory to open file :\n%s", file);
  234.     ErrorMsg("Open File", db_msg);
  235.     return 0;
  236.   }
  237.  
  238.   DB_Grab();
  239.  
  240.   while(fgets(dataString, sizeof(dataString), sqlf) != NULL){
  241.     DB_WriteToBuffer(dataString, tmp_buffer->buffer);
  242.   }
  243.  
  244.   DB_UnGrab();
  245.  
  246.   if(fclose(sqlf) != 0){
  247.     sprintf(db_msg, "Error closing file:\n%s", file);
  248.     ErrorMsg("Open File", db_msg);
  249.     return 0;
  250.   }
  251.   
  252.   buffer_curr = DB_SetBuffer(tmp_buffer);
  253.   return 1;
  254. }
  255.  
  256. /************************************************************************/
  257. /* Function: DB_SaveFile                                                */
  258. /* Purpose : saves a buffer into its source file                        */
  259. /* Params  : buffer : ptr to buffer to save                             */
  260. /* Returns : 1 on SUCCESS / 0 on FAILURE                                */
  261. /* Notes   :                                                            */
  262. /************************************************************************/
  263.  
  264. int DB_SaveFile(LLISTbuffer *buffer)
  265. {
  266.   FILE *sqlf;
  267.   char *data;
  268.   char db_msg[ERR_MSG_SIZE];
  269.  
  270.   if((sqlf = fopen(buffer->filename, "w+")) == NULL){
  271.     sprintf(db_msg, "Error opening: %s", buffer->filename);
  272.     ErrorMsg("Save", db_msg);
  273.     return 0;
  274.   }
  275.  
  276.   data = XmTextGetString(buffer->buffer);
  277.  
  278.   DB_Grab();
  279.  
  280.   fputs(data, sqlf);
  281.   fflush(sqlf);
  282.  
  283.   DB_UnGrab();
  284.  
  285.   if(fclose(sqlf) != 0){
  286.     sprintf(db_msg, "Error closing file: %s", buffer->filename);
  287.     ErrorMsg("Save", db_msg);
  288.     return 0;
  289.   }
  290.   buffer->modified = 0;
  291.   DB_SetTitle(buffer->filename);
  292.   sprintf(db_msg, "Saved file: %s", buffer->filename);
  293.   XtVaSetValues(AppWidgetsPtr->message,
  294.         XtVaTypedArg, XmNlabelString, XmRString,
  295.         db_msg, strlen(db_msg)+1, NULL);
  296.  
  297.   return 1;
  298. }
  299.  
  300. /************************************************************************/
  301. /* Function: DB_PrintTuples                                             */
  302. /* Purpose : prints query results to selected destination               */
  303. /* Params  : qy : string w/ qy                                          */
  304. /*           res: query result struct                                   */
  305. /*           fout: string w/ file to write to                           */
  306. /*           Spool: spooling flag 0=FALSE / 1=TRUE                      */
  307. /*           PrintAttNames: print attribute names 0=FALSE / 1=TRUE      */
  308. /*           TerseOutput: print terse output 0=FALSE / 1=TRUE           */
  309. /*           Echo: echo query 0=FALSE / 1=TRUE                          */
  310. /*           colWidth: width of output columns                          */
  311. /* Returns :                                                            */
  312. /* Notes   :                                                            */
  313. /************************************************************************/
  314.  
  315. void DB_PrintTuples(char *qy, PGresult *res, char *fout, int Spool, int PrintAttNames, 
  316.             int Echo, int colWidth, char sep)
  317. {
  318.   FILE *spoolf;
  319.   int nFields; 
  320.   int nTups;
  321.   int i,j;
  322.   char formatString[80];
  323.   char dataString[DATA_SIZE];
  324.   
  325.   char *tborder = NULL;
  326.   
  327.   nFields = PQnfields(res);
  328.   nTups = PQntuples(res);
  329.  
  330.   if(Spool){
  331.     if((spoolf = fopen(fout, "w+")) == NULL){
  332.       sprintf(dataString, "Error opening/creating file: %s\n", fout);
  333.       DB_WriteToResult(dataString, 0, NULL);
  334.       return;
  335.     }
  336.   }
  337.  
  338.   if(Echo){
  339.     sprintf(dataString, "QUERY: %s\n\n", 
  340.         (char *)doubleTrim(qy));
  341.     DB_WriteToResult(dataString, Spool, spoolf);
  342.   }
  343.  
  344.   if (colWidth > 0) {
  345.     if(sep == '\0')
  346.        sprintf(formatString,"%%s%%-%ds", colWidth);
  347.     else
  348.       sprintf(formatString,"%%s%%-%ds%c", colWidth, sep);
  349.   } else
  350.     sprintf(formatString,"%%s%%s%c", sep);
  351.   
  352.   if ( nFields > 0 ) {  /* only print tuples with at least 1 field.  */
  353.     
  354.     if (PrintAttNames)
  355.       {
  356.     int width;
  357.     width = nFields * colWidth;
  358.     tborder = XtMalloc (width+1);
  359.     for (i = 0; i <= width; i++) 
  360.       tborder[i] = '-';
  361.     tborder[i] = '\0';
  362.       }
  363.     
  364.     for (i=0; i < nFields; i++) {
  365.       if (PrintAttNames) {
  366.     sprintf(dataString,formatString,
  367.         "", PQfname(res, i));
  368.     if(i == (nFields - 1)) 
  369.       dataString[strlen(dataString) - 1] = '\0';
  370.     DB_WriteToResult(dataString, Spool, spoolf);
  371.       }
  372.     }
  373.     
  374.     if (PrintAttNames) {
  375.       sprintf(dataString,"\n%s\n", tborder);
  376.       DB_WriteToResult(dataString, Spool, spoolf);
  377.     }
  378.     
  379.     for (i = 0; i < nTups; i++) { 
  380.       if(XmTextGetLastPosition(AppWidgetsPtr->resultwindow) > RSLT_BUFFER_SIZE)
  381.     DB_ShrinkBuffer(AppWidgetsPtr->resultwindow);
  382.  
  383.       for (j = 0; j < nFields; j++) {
  384.     char *pval = PQgetvalue(res,i,j);
  385.     sprintf(dataString, formatString,
  386.         "", pval ? pval : "");
  387.     if(j == (nFields - 1)) 
  388.       dataString[strlen(dataString) - 1] = '\0';
  389.     DB_WriteToResult(dataString, Spool, spoolf);
  390.       }
  391.       sprintf(dataString,"\n");
  392.       DB_WriteToResult(dataString, Spool, spoolf);
  393.     }
  394.     DB_WriteToResult("\n", Spool, spoolf);
  395.     XtFree(tborder);
  396.  
  397.     if(Spool){
  398.       if(fclose(spoolf) != 0){
  399.     sprintf(dataString, "Error closing file: %s\n", fout);
  400.     DB_WriteToResult(dataString, 0, NULL);
  401.     return;
  402.       }
  403.       DB_WriteToResult("Query finished.\n", 0, NULL);  
  404.     }
  405.   }
  406. }
  407.  
  408. /************************************************************************/
  409. /* Function: DB_WriteToResult                                           */
  410. /* Purpose : writes data to result window                               */
  411. /* Params  : data : string w/ data to write                             */
  412. /*           spool: spool flag 0=FALSE / 1=TRUE                         */
  413. /*           file : spool file (FILE*)                                  */
  414. /* Returns :                                                            */
  415. /* Notes   :                                                            */
  416. /************************************************************************/
  417.  
  418. void DB_WriteToResult(char *data, int spool, FILE *file)
  419. {
  420.   XmTextPosition ins_pos;
  421.  
  422.   if(spool)
  423.     fprintf(file, data);
  424.   else{
  425.     ins_pos = XmTextGetLastPosition(AppWidgetsPtr->resultwindow);
  426.     XmTextInsert(AppWidgetsPtr->resultwindow, ins_pos, data);
  427.     XmTextShowPosition(AppWidgetsPtr->resultwindow,
  428.                        XmTextGetLastPosition(AppWidgetsPtr->resultwindow)+1);
  429.   }
  430. }
  431.  
  432. /************************************************************************/
  433. /* Function: DB_WriteToSQL                                              */
  434. /* Purpose : writes data to SQL window                                  */
  435. /* Params  : data : string w/ data to write                             */
  436. /* Returns :                                                            */
  437. /* Notes   :                                                            */
  438. /************************************************************************/
  439.  
  440. void DB_WriteToSQL(char *data)
  441. {
  442.   XmTextPosition ins_pos;
  443.  
  444.   ins_pos = XmTextGetLastPosition(AppWidgetsPtr->sqlwindow);
  445.   XmTextInsert(AppWidgetsPtr->sqlwindow, ins_pos, data);
  446. }
  447.  
  448. /************************************************************************/
  449. /* Function: DB_WriteToBuffer                                           */
  450. /* Purpose : writes data to text widget (buffer)                        */
  451. /* Params  : data : string w/ data to write                             */
  452. /*           w : text widget to write to (buffer)                       */
  453. /* Returns :                                                            */
  454. /* Notes   :                                                            */
  455. /************************************************************************/
  456.  
  457. void DB_WriteToBuffer(char *data, Widget w)
  458. {
  459.   XmTextPosition ins_pos;
  460.  
  461.   ins_pos = XmTextGetLastPosition(w);
  462.   XmTextInsert(w, ins_pos, data);
  463. }
  464.  
  465. /************************************************************************/
  466. /* Function: DB_OpenScratchBuffer                                       */
  467. /* Purpose : opens a new scratch buffer                                 */
  468. /* Params  :                                                            */
  469. /* Returns : ptr to new buffer on SUCCESS / NULL on FAILURE             */
  470. /* Notes   :                                                            */
  471. /************************************************************************/
  472.  
  473. LLISTbuffer* DB_OpenScratchBuffer(void)
  474. {
  475.   char db_msg[ERR_MSG_SIZE];
  476.   LLISTbuffer *tmp_buffer;
  477.  
  478.   if((tmp_buffer = LLIST_Insert(0, "scratch", buffer_tail)) == NULL){
  479.     sprintf(db_msg, "Not enough memory to open buffer.");
  480.     ErrorMsg("New", db_msg);
  481.     return NULL;
  482.   }
  483.   else
  484.     return tmp_buffer;
  485. }
  486.  
  487. /************************************************************************/
  488. /* Function: DB_SetBuffer                                               */
  489. /* Purpose : sets a select buffer to current SQL window buffer          */
  490. /* Params  : buffer : ptr to buffer to display                          */
  491. /* Returns : ptr to new current buffer                                  */
  492. /* Notes   :                                                            */
  493. /************************************************************************/
  494.  
  495. LLISTbuffer* DB_SetBuffer(LLISTbuffer *buffer)
  496. {
  497.   XmTextSource sql_src;
  498.   XmTextSource buffer_src;
  499.  
  500.   buffer_src = XmTextGetSource(buffer->buffer);
  501.   XmTextSetSource(AppWidgetsPtr->sqlwindow, buffer_src, 0, 0);
  502.  
  503.   sql_src = XmTextGetSource(AppWidgetsPtr->sqlwindow);
  504.   XmTextSetSource(buffer->buffer, sql_src, 0, 0);
  505.  
  506.   DB_SetTitle(buffer->filename);
  507.  
  508.   return buffer;
  509. }
  510.  
  511. /************************************************************************/
  512. /* Function: DB_SetTitle                                                */
  513. /* Purpose : sets app's title window to passed string                   */
  514. /* Params  : win_title : string w/ window title                         */
  515. /* Returns :                                                            */
  516. /* Notes   :                                                            */
  517. /************************************************************************/
  518.  
  519. void DB_SetTitle(char *win_title)
  520. {
  521.   char title[MAX_PATH_LEN]= "MPSQL - ";
  522.  
  523.   XtVaSetValues(AppWidgetsPtr->shell,
  524.         XmNtitle, strcat(title, win_title),
  525.         NULL);
  526.  
  527. }
  528.  
  529. /************************************************************************/
  530. /* Function: DB_DeleteBuffer                                            */
  531. /* Purpose : deletes a buffer                                           */
  532. /* Params  : buffer : ptr to buffer to delete                           */
  533. /* Returns :                                                            */
  534. /* Notes   :                                                            */
  535. /************************************************************************/
  536.  
  537. void DB_DeleteBuffer(LLISTbuffer *buffer)
  538. {
  539.   if((LLIST_Count() - 1) == 0){
  540.     DB_OpenScratchBuffer();
  541.     buffer_curr = DB_SetBuffer(buffer_tail->prev);
  542.   }
  543.   else{
  544.     if(buffer->prev == buffer_head)
  545.       buffer_curr = DB_SetBuffer(buffer->next);
  546.     else 
  547.       buffer_curr = DB_SetBuffer(buffer->prev);
  548.   }
  549.   LLIST_Delete(buffer);
  550.  
  551. /************************************************************************/
  552. /* Function: DB_PrintBuffer                                             */
  553. /* Purpose : prints contents of a buffer                                */
  554. /* Params  : buffer : ptr to buffer to print                            */
  555. /*           printer: ptr to printer command string to use              */
  556. /* Returns :                                                            */
  557. /* Notes   :                                                            */
  558. /************************************************************************/
  559.  
  560. void DB_PrintBuffer(LLISTbuffer *buffer, char *printer)
  561. {
  562.   char tmp_file[MAX_PATH_LEN];
  563.   char tmp_name[MAX_PATH_LEN];
  564.   char print[MAX_PATH_LEN];
  565.   FILE *sqlf;
  566.   char *data;
  567.   char db_msg[ERR_MSG_SIZE];
  568.  
  569.   sprintf(tmp_file, "%s", tmpnam(tmp_name));
  570.  
  571.   if((sqlf = fopen(tmp_file, "w+")) == NULL){
  572.     sprintf(db_msg, "Error opening tmp file: %s", tmp_file);
  573.     ErrorMsg("Print", db_msg);
  574.     return;
  575.   }
  576.  
  577.   data = XmTextGetString(buffer->buffer);
  578.  
  579.   fputs(data, sqlf);
  580.   fflush(sqlf);
  581.  
  582.   if(fclose(sqlf) != 0){
  583.     sprintf(db_msg, "Error closing tmp file: %s", tmp_file);
  584.     ErrorMsg("Print", db_msg);
  585.     return;
  586.   }
  587.  
  588.   sprintf(print, "%s %s",
  589.       doubleTrim((char *)XmTextGetString(AppWidgetsPtr->printer)) ,tmp_file); 
  590.   system(print);
  591.   sprintf(print, "rm -f %s", tmp_file);
  592.   system(print);
  593. }
  594.  
  595. /************************************************************************/
  596. /* Function: DB_ChkModBuffers                                           */
  597. /* Purpose : checks the linked list for modified buffers                */
  598. /* Params  :                                                            */
  599. /* Returns : 0 all saved / 1 unsaved buffers                            */
  600. /* Notes   :                                                            */
  601. /************************************************************************/
  602.  
  603. int DB_ChkModBuffers(void)
  604. {
  605.   int i;
  606.   LLISTbuffer *curr;
  607.  
  608.   for(i = 1; i <= LLIST_Count(); i++){
  609.     curr = LLIST_Get(i);
  610.     if(curr->modified == 1)
  611.       return 1;
  612.   }
  613.   return 0;
  614. }
  615.  
  616. /************************************************************************/
  617. /* Function: DB_ShrinkBuffer                                            */
  618. /* Purpose : removes text from top of specified text widget             */
  619. /* Params  : w : text widget to remove text from                        */
  620. /* Returns : nothing                                                    */
  621. /* Notes   :                                                            */
  622. /************************************************************************/
  623.  
  624. void DB_ShrinkBuffer(Widget w)
  625. {
  626.   int i;
  627.   char *txt = XmTextGetString(w);
  628.  
  629.   while(XmTextGetLastPosition(w) >= RSLT_BUFFER_SIZE){
  630.     i = 0;
  631.     while(txt[i] != '\n') 
  632.       i++;
  633.     XmTextReplace(w, 0, ++i, "");
  634.   }
  635. }
  636.  
  637. /************************************************************************/
  638. /* Function: DB_HandleCopyOut                                           */
  639. /* Purpose : copies data out as specified by passed copy command        */
  640. /* Params  : res: result set from copy command                          */
  641. /* Returns : nothing                                                    */
  642. /* Notes   :                                                            */
  643. /************************************************************************/
  644.  
  645. void DB_HandleCopyOut(PGresult *res)
  646. {
  647.     bool copydone = false;
  648.     char copybuf[COPYBUFSIZ];
  649.     int ret;
  650.     
  651.     while (!copydone) {
  652.     ret = PQgetline(res->conn, copybuf, COPYBUFSIZ);
  653.     
  654.     if (copybuf[0] == '.' && copybuf[1] =='\0') {
  655.         copydone = true;    /* don't print this... */
  656.     } else {
  657.         fputs(copybuf, stdout);
  658.         switch (ret) {
  659.         case EOF:
  660.         copydone = true;
  661.         case 0:
  662.         fputc('\n', stdout);
  663.         break;
  664.         case 1:
  665.         break;
  666.         }
  667.     }
  668.     }
  669.     fflush(stdout);
  670.     PQendcopy(res->conn);
  671. }
  672.  
  673. /************************************************************************/
  674. /* Function: DB_HandleCopyIn                                            */
  675. /* Purpose : copies data in as specified by passed copy command         */
  676. /* Params  : res: result set from copy command                          */
  677. /* Returns : nothing                                                    */
  678. /* Notes   :                                                            */
  679. /************************************************************************/
  680.  
  681. void DB_HandleCopyIn(PGresult *res)
  682. {
  683.     bool copydone = false;
  684.     bool firstload;
  685.     bool linedone;
  686.     char copybuf[COPYBUFSIZ];
  687.     char *s;
  688.     int buflen;
  689.     int c;
  690.     
  691.     fflush(stdin);
  692.     if ((c = getc(stdin)) != '\n' && c != EOF) {
  693.     (void) ungetc(c, stdin);
  694.     }
  695.     
  696.     while (!copydone) {            /* for each input line ... */
  697.     firstload = true;
  698.     linedone = false;
  699.     while (!linedone) {        /* for each buffer ... */
  700.         s = copybuf;
  701.         buflen = COPYBUFSIZ;
  702.         for (; buflen > 1 &&
  703.          !(linedone = (c = getc(stdin)) == '\n' || c == EOF);
  704.          --buflen) {
  705.         *s++ = c;
  706.         }
  707.         if (c == EOF) {
  708.         /* reading from stdin, but from a file */
  709.         PQputline(res->conn, ".");
  710.         copydone = true;
  711.         break;
  712.         }
  713.         *s = '\0';
  714.         PQputline(res->conn, copybuf);
  715.         if (firstload) {
  716.         if (!strcmp(copybuf, ".")) {
  717.             copydone = true;
  718.         }
  719.         firstload = false;
  720.         }
  721.     }
  722.     PQputline(res->conn, "\n");
  723.     }
  724.     PQendcopy(res->conn);
  725. }
  726.  
  727. /************************************************************************/
  728. /* Function: DB_Grab                                                    */
  729. /* Purpose : Grabs input events                                         */
  730. /* Params  :                                                            */
  731. /* Returns : nothing                                                    */
  732. /* Notes   :                                                            */
  733. /************************************************************************/
  734.  
  735. void DB_Grab(void)
  736. {
  737.   XDefineCursor(XtDisplay(AppWidgetsPtr->mainwindow),
  738.         XtWindow(AppWidgetsPtr->mainwindow),
  739.         XCreateFontCursor(XtDisplay(AppWidgetsPtr->mainwindow),
  740.                   XC_watch));
  741.  
  742.   XtGrabButton(AppWidgetsPtr->mainwindow,
  743.            AnyButton,
  744.            AnyModifier,
  745.            TRUE,
  746.            ButtonPressMask|ButtonMotionMask|ButtonReleaseMask|
  747.            LeaveWindowMask|EnterWindowMask|FocusChangeMask,
  748.            GrabModeAsync,
  749.            GrabModeAsync,
  750.            None,
  751.            None);
  752. }
  753.  
  754. /************************************************************************/
  755. /* Function: DB_UnGrab                                                  */
  756. /* Purpose : UnGrabs input events                                       */
  757. /* Params  :                                                            */
  758. /* Returns : nothing                                                    */
  759. /* Notes   :                                                            */
  760. /************************************************************************/
  761.  
  762. void DB_UnGrab(void)
  763. {
  764.   XtUngrabButton(AppWidgetsPtr->mainwindow, AnyButton, AnyModifier);
  765.   XUndefineCursor(XtDisplay(AppWidgetsPtr->mainwindow),
  766.           XtWindow(AppWidgetsPtr->mainwindow));
  767. }
  768.  
  769.  
  770.